#include "Task.hpp"
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <assert.h>


//const vector<int> task;

vector<function<void()>> tasks;



class channel//子进程描述对象
{
public:
    channel(pid_t pid,const string& processname,int cmdfd)
    :
    _pid(pid),_processname(processname),_cmdfd(cmdfd)
    {}

public:
    int _cmdfd;
    const string& _processname;
    pid_t _pid;
};




void Slaver()
{
    int cut=5;
    while(cut--)
    {
        int cmdcode=0;
        int n=read(0,&cmdcode,sizeof(int));
        if(n==0)break;
        if(n==sizeof(int))
        {
            if(cmdcode>=0&&cmdcode<4)
            {
                cout<<"get slaver success slaver is task "<<cmdcode+1<<" "<<"i am "<<getpid()<<endl;
                tasks[cmdcode]();
            } 
        }
    }
}



void InitProcessPool(vector<channel> *channels)
{
    int cut=5;
    vector<int> oldfds;
    while(cut--)
    {
        int pipefd[2];
        int n=pipe(pipefd);
        assert(n==0);
        pid_t pid=fork();
        //cout<<pid<<endl;
        string name="ProcessPool-"+(5-cut+'0');
        //if(pid<0) continue;
        if(pid==0)
        {
            for(auto &fd:oldfds)
            {
                close(fd);
            }
            //子进程要读，关闭1
            close(pipefd[1]);
            dup2(pipefd[0],0);
            close(pipefd[0]);
            cout<<"Init success i am child "<<(5-cut)<<endl;
            Slaver();
            exit(0);
        }
        else
        {
            //注意channels是父进程需要管理的对象
            channels->push_back(channel(pid,name,pipefd[1]));
            //父进程要写，关闭0
            close(pipefd[0]);
            oldfds.push_back(pipefd[1]);
            //waitpid(pid,nullptr,0);

            //sleep(1);
        }
    }
    sleep(1);
}

void CtrlSlaver(const vector<channel> &channels)
{
    srand(time(nullptr));
    int cut=16;
    while(cut--)
    {
        int cmdcode=rand()%4;
        int childnum=rand()%channels.size();
        write(channels[childnum]._cmdfd,&cmdcode,sizeof(cmdcode));
        //sleep(1);
    }
}

void QuitProcess(const vector<channel> &channels)
{
    for(auto &cmd:channels)
    {
        close(cmd._cmdfd);
        waitpid(cmd._pid,nullptr,0);
    }
}


int main()
{
    cout<<getpid()<<endl;

    loadtask(&tasks);//获取task任务

    vector<channel> channels;//子进程组织

    InitProcessPool(&channels);//初始化进程

    CtrlSlaver(channels);//控制子进程，给子进程派发任务

    sleep(15);

    QuitProcess(channels);//回收子进程

    sleep(10);

    cout<<"Process end!!!!"<<endl;
    
    return 0;
}